package common.util.gbkToUtf;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
/**
* 类说明：
* 设置eclipse IDE中的文件编码会影响读取文件时候采用的编码。
* 读入后都转换为itf-8。
* 
* JDK1.5中可以用构造函数:
* String(byte[] bytes, int offset, int length, String charsetName) 
*/
public class GbkToUtf {
/**
* @param args */

/**
* 以指定编码方式写文本文件，存在会覆盖
* @param file
* @param charsetName
* @param content
* @throws Exception
*/
public static File saveFileWithCharsetName(File file,String charsetName,String content) throws Exception {  
   System.out.println("convert file:"+file.getAbsolutePath());
   String originalPath = file.getAbsolutePath();
   String outPutPath = originalPath.replace(SOURCE_DIR, OUTPUT_DIR);
   File newFile = new File(outPutPath);
   File parent = newFile.getParentFile();
   if(!parent.exists()){
	   parent.mkdirs();
   }
   newFile.createNewFile();
   FileOutputStream fileOut = new FileOutputStream(newFile);
   //CharsetDecoder
   OutputStreamWriter outWrite=new OutputStreamWriter(fileOut,Charset.forName(charsetName));
   outWrite.write(content);
   outWrite.close(); 
   return newFile;
}

/**
* 以指定编码方式读取文本文件，返回文件内容
* @param file
* @param charsetName
* @return
* @throws Exception
*/
public static String getFileContentWithCharsetName(File file,String charsetName) throws Exception {  
   FileInputStream fileIn = new FileInputStream(file);
   //CharsetDecoder
   InputStreamReader inRead=new InputStreamReader(fileIn,Charset.forName(charsetName));
   int size=(int)(file.length());  
   char[] chs=new char[size];
   inRead.read(chs);
   String str=new String(chs).trim(); 
   inRead.close();
   return str;  
}


private final static String SOURCE_ENCODING = "GBK";
private final static String TARGET_ENCODING = "UTF-8";
private static boolean addBom = true;

//private static final String OUTPUT_DIR = "D:\\MyData\\desk\\encodedData";
//private static final String OUTPUT_DIR_BOM = "D:\\MyData\\desk\\encodedData_bom";
//private static final String SOURCE_DIR = "E:\\newsvn\\Kom_New_Client_ios";

//private static final String OUTPUT_DIR = "D:\\MyData\\desk\\encodedData";
//private static final String OUTPUT_DIR_BOM = "D:\\MyData\\desk\\encodedData_bom";
//private static final String SOURCE_DIR = "E:\\newsvn\\Kom_New_Client";

private static final String OUTPUT_DIR = "D:\\MyData\\desk\\encodedData";
private static final String OUTPUT_DIR_BOM = "D:\\MyData\\desk\\encodedData_bom";
private static final String SOURCE_DIR = "E:\\workspace\\cocos2d\\cocos2dResources\\cocos2d-x-current\\myproj\\myCocosTest\\Classes";


private static String[] fileType = {"java","cs","h","cpp"};

/**
 * @param args
 */
public static void main(String[] args) {
 try {
  exchange(SOURCE_DIR);
 } catch (Exception e) {
  e.printStackTrace();
 }
}

/**
 * exchange the character encoding from srcDir to targetDir
 * 
 * @param srcDir
 * @param targetDir
 * @throws Exception 
 */
public static void exchange(String srcDir) throws Exception {
 String absPath = "";
 if (!srcDir.equals(SOURCE_DIR)) {
  absPath = srcDir.substring(SOURCE_DIR.length());
 }

 File sourceDirectory = new File(srcDir);
 if (sourceDirectory.exists()) {
  if (sourceDirectory.isFile()) {
	  boolean filterType = false;
	  for(int i =0 ;i<fileType.length;i++){
		  if(sourceDirectory.getName().endsWith(fileType[i])){
			  filterType=true;
		  }
	  }
	  if(filterType){
		  String sourceEncode = getCharset(sourceDirectory);
		  if(sourceEncode.equals("GBK")){
			  try {
			    fileEncodingExchange(sourceDirectory);
			  } catch (IOException e) {
			    e.printStackTrace();
			  }
		  }else{
			  System.out.println("file ::"+sourceDirectory.getAbsolutePath()+"   is not gbk::"+sourceEncode);
		  }
	  }
  } else {
   File[] childs = sourceDirectory.listFiles();

   for (File child : childs)
    exchange(child.getPath());
  }
 }
}

private static void fileEncodingExchange(File infile) throws IOException {
   try {
    String content=getFileContentWithCharsetName(infile,SOURCE_ENCODING);
    File newFile = saveFileWithCharsetName(infile,TARGET_ENCODING, content);
    if(addBom){
    	addBom(newFile);
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
}

private static void addBom(File file){
	InputStream in = null;
	try {
        BufferedInputStream inBuff = null;
        BufferedOutputStream outBuff = null;
        try {
            // 新建文件输入流并对它进行缓冲
            inBuff = new BufferedInputStream(new FileInputStream(file));
            String originalPath = file.getAbsolutePath();
            String realPath = originalPath.replace(OUTPUT_DIR, OUTPUT_DIR_BOM);
            File newFile = new File(realPath);
            File parent = newFile.getParentFile();
            if(!parent.exists()){
         	   parent.mkdirs();
            }
            newFile.createNewFile();
            
            // 新建文件输出流并对它进行缓冲
            outBuff = new BufferedOutputStream(new FileOutputStream(newFile));

            byte[] bom = new byte[3];
            bom[0] = Byte.parseByte(""+14);
            bom[0] = (byte) 0xef;
            bom[1] = (byte) 0xbb;
            bom[2] = (byte) 0xbf;
            outBuff.write(bom, 0, 3);
            // 缓冲数组
            byte[] b = new byte[1024 * 5];
            int len;
            
            while ((len = inBuff.read(b)) != -1) {
            	for(int i=0;i<b.length;i++){
            		System.out.println(b[i]);
            	}
                outBuff.write(b, 0, len);
            }
            bom[0]= (byte) 0x0d;
            bom[1]= (byte) 0x0a;
            outBuff.write(bom, 0, 2);
            // 刷新此缓冲的输出流
            outBuff.flush();
        } finally {
            // 关闭流
            if (inBuff != null)
                inBuff.close();
            if (outBuff != null)
                outBuff.close();
        }
        
    } catch (IOException e) {
        e.printStackTrace();
        return;
    }
}


/**
 * 判断文件的编码格式
 * @param fileName :file
 * @return 文件编码格式
 * @throws Exception
 */
public static String codeString(File file) throws Exception{
	BufferedInputStream bin = new BufferedInputStream(
	new FileInputStream(file));
	int p = (bin.read() << 8) + bin.read();
	String code = null;
	System.out.println(p);
	switch (p) {
		case 0xefbb:
			code = "UTF-8";
			break;
		case 0xfffe:
			code = "Unicode";
			break;
		case 0xfeff:
			code = "UTF-16BE";
			break;
		default:
			code = "GBK";
	}
	
	return code;
}


public static String getCharset(File file)
{
    
    String charset = "GBK";
    byte[] first3Bytes = new byte[3];
    BufferedInputStream bis = null;
    try
    {
        //boolean checked = false;
        bis = new BufferedInputStream(new FileInputStream(file));
        bis.mark(0);
        int read = bis.read(first3Bytes, 0, 3);
        if (read == -1)
        {
            return charset;
        }
        if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE)
        {
            charset = "UTF-16LE";
            //checked = true;
        }
        else if (first3Bytes[0] == (byte) 0xFE
                && first3Bytes[1] == (byte) 0xFF)
        {
            charset = "UTF-16BE";
            //checked = true;
        }
        else if (first3Bytes[0] == (byte) 0xEF
                && first3Bytes[1] == (byte) 0xBB
                && first3Bytes[2] == (byte) 0xBF)
        {
            charset = "UTF-8";
            //checked = true;
        }
        /*******************************************************************
         * bis.reset(); if (!checked) { int loc = 0; while ((read =
         * bis.read()) != -1) { loc++; if (read >= 0xF0) { break; } if (0x80 <=
         * read && read <= 0xBF) // 单独出现BF以下的，也算是GBK { break; } if (0xC0 <=
         * read && read <= 0xDF) { read = bis.read(); if (0x80 <= read &&
         * read <= 0xBF)// 双字节 (0xC0 - 0xDF) { // (0x80 - 0xBF),也可能在GB编码内
         * continue; } else { break; } } else if (0xE0 <= read && read <=
         * 0xEF) { // 也有可能出错，但是几率较小 read = bis.read(); if (0x80 <= read &&
         * read <= 0xBF) { read = bis.read(); if (0x80 <= read && read <=
         * 0xBF) { charset = "UTF-8"; break; } else { break; } } else {
         * break; } } } System.out.println(loc + " " +
         * Integer.toHexString(read)); }
         ******************************************************************/
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        if (bis != null)
        {
            try
            {
                bis.close();
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
    }
    return charset;
}

}